package org.rcy.framework.thrift.struct;

import org.apache.thrift.TException;
import org.rcy.framework.thrift.metadata.FieldIdEnum;
import org.rcy.framework.thrift.metadata.FieldMetaData;
import org.rcy.framework.thrift.metadata.MetaDataBuilder;
import org.rcy.framework.thrift.metadata.StructMetaData;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;

public class ThriftStruct extends AbstractStruct {

	private static final long serialVersionUID = 1L;

	private final StructMetaData structMetaData;

	private final Map<FieldIdEnum, Field> fieldMap = new HashMap();

	/**
	 * 实体类型对象Trift数据格式封装
	 * @param structMetaData
	 * @param structObject
	 * @throws TException
	 *  //TODO 未解决对象循环依赖问题
	 */
	public ThriftStruct(StructMetaData structMetaData, Object structObject) throws TException {
		this.structMetaData = structMetaData;
		Class<?> structClass = structMetaData.structClass;
		Field[] fields = getAllFields(structClass);
		short index = 1;// 序号从1开始
		for (Field javaField : fields) {
			if (!needSerialize(javaField)) {
				continue;
			}
			javaField.setAccessible(true);

			Type fieldType = javaField.getGenericType();
			FieldIdEnum field = new FieldIdEnum(index, javaField.getName());

			FieldMetaData metaData = MetaDataBuilder.fieldMetaData(field, fieldType,structMetaData.getTypeArguments());
			addMetaData(field, metaData);
			fieldMap.put(field, javaField);

			if (structObject != null) {
				try {
					Object value = javaField.get(structObject);
					addValue(field, value);
				} catch (Exception e) {
					throw new TException(e);
				}
			}

			index++;
		}
	}

	/**
	 * Read完成之后获取Struct对象
	 * 
	 * @return
	 * @throws InstantiationException 
	 * @throws Exception
	 */
	public Object getStructObject() throws TException {
		try {
			Class<?> beanClass = structMetaData.structClass;
			// 反射创建对象,必须有一个无参的构造函数
			Object bean = beanClass.newInstance();
			SortedMap<FieldIdEnum, Object> valueMap = getValueMap();
			// 给对象的字段赋值
			for (FieldIdEnum fieldIdEnum : valueMap.keySet()) {
				Object value = valueMap.get(fieldIdEnum);
				Field field = fieldMap.get(fieldIdEnum);
				field.set(bean, value);
			}
			return bean;
		} catch (Exception e) {
			logger.warn(e.getMessage(),e);
			throw new TException(e.getMessage());
		}
	}
	
	protected boolean needSerialize(Field javaField){
		int modifier = javaField.getModifiers();
		// Transient,Static类型的字段不会序列化
		if (Modifier.isTransient(modifier) || Modifier.isStatic(modifier)) {
			return false;
		}
		return true;
	}

}
